package com.sunlands.zlcx.usercenter.service;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.sunlands.zlcx.usercenter.constant.LearningStatus;
import com.sunlands.zlcx.usercenter.constant.NameStatus;
import com.sunlands.zlcx.usercenter.constant.RedisKeyConst;
import com.sunlands.zlcx.usercenter.domain.UsersLearnTimingDO;
import com.sunlands.zlcx.usercenter.domain.share.UserShareCardDO;
import com.sunlands.zlcx.usercenter.domain.share.UserShareInfoDO;
import com.sunlands.zlcx.usercenter.domain.share.UserShareZanDO;
import com.sunlands.zlcx.usercenter.exception.CheckParamException;
import com.sunlands.zlcx.usercenter.exception.CheckRunException;
import com.sunlands.zlcx.usercenter.repository.share.UsersShareCardRepository;
import com.sunlands.zlcx.usercenter.repository.share.UsersShareInfoRepository;
import com.sunlands.zlcx.usercenter.repository.share.UsersShareZanRepository;
import com.sunlands.zlcx.usercenter.util.AssertUtil;
import com.sunlands.zlcx.usercenter.util.BeanPropertiesUtil;
import com.sunlands.zlcx.usercenter.vo.*;
import com.sunlands.zlcx.usercenter.vo.share.UserShareCardVO;
import com.sunlands.zlcx.usercenter.vo.share.UserShareInfoVO;
import com.sunlands.zlcx.usercenter.vo.share.UserShareZanVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author gaoyanfeng
 * description: 学习目标
 */
@Service
@Slf4j
public class UsersShareServiceImpl implements BeanPropertiesUtil{

    public void add(UserShareInfoDO userShareInfoDO) {
        UsersVO usersVO = usersService.find(userShareInfoDO.getUserId());
        if (null == usersVO) {
            log.info("用户信息不存在 usersVO={}", usersVO);
            throw new CheckParamException(CommonResultMessage.INVALID_USER.data);
        }
        UserShareInfoDO userShareInfoFromDB = getShareInfoByLearnId(userShareInfoDO.getLearnId());
        if (userShareInfoFromDB != null) {
            log.info("分享记录已经创建 learnId={}", userShareInfoDO.getLearnId());
            return;
        }
        UsersLearnTimingDO learnTimingDOById = usersStudyService.getLearnTimingDOById(userShareInfoDO.getLearnId());
        String shareName = learnTimingDOById.getLearnName();
        if ("学习计时".equals(learnTimingDOById.getLearnName())) {
            shareName = "";
        }
        if (LearningStatus.ifOrdernaryLearn(usersVO.getStatus())) {
            userShareInfoDO.setStatus(UserShareInfoDO.Status.LEARNING.getCode());
            userShareInfoDO.setShareContent(usersVO.getName()+"正在学习"+shareName+"中");
        } else {
            userShareInfoDO.setStatus(UserShareInfoDO.Status.LEARN_OVER.getCode());
            userShareInfoDO.setShareContent(usersVO.getName()+"完成了学习"+shareName);
        }
        UserShareInfoDO save = usersShareInfoRepository.save(userShareInfoDO);
        String shareInfoKey = RedisKeyConst.getShareInfo(save.getLearnId());
        redisTemplate.opsForValue().set(shareInfoKey, save);
    }

    public void updateShareContentAndStatusByLearnId(Long learnId, Integer nameStatus, String learnName, String userName) {
        UserShareInfoDO userShareInfoDO = getShareInfoByLearnId(learnId);
        if (null == userShareInfoDO) {
            log.info("没有可以修改的分享 learnId={}", learnId);
            return;
        }
        NameStatus nameStatusEnum = NameStatus.getLearningStatus(nameStatus);
        if (learnName.equals("学习计时")) {
            learnName="";
        }
        if (nameStatusEnum == NameStatus.LEARN_TIMING) {
            userShareInfoDO.setShareContent(userName+"正在学习"+learnName+"中");
            userShareInfoDO.setStatus(UserShareInfoDO.Status.LEARNING.getCode());
        } else if (nameStatusEnum == NameStatus.LEARN_AFTER) {
            userShareInfoDO.setStatus(UserShareInfoDO.Status.LEARN_OVER.getCode());
            userShareInfoDO.setShareContent(userName+"完成了学习"+learnName);
        }
        usersShareInfoRepository.save(userShareInfoDO);
        redisTemplate.delete(RedisKeyConst.getShareInfo(learnId));
    }

    public UserShareInfoDO getShareInfoByLearnId(Long learnId) {
        String shareInfoKey = RedisKeyConst.getShareInfo(learnId);
        Object o = redisTemplate.opsForValue().get(shareInfoKey);
        UserShareInfoDO userShareInfoDO = null;
        if (null == o) {
            userShareInfoDO = usersShareInfoRepository.findByLearnId(learnId);
            if (null != userShareInfoDO) {
                redisTemplate.opsForValue().set(shareInfoKey, userShareInfoDO, 1, TimeUnit.DAYS);
            }
            return userShareInfoDO;
        }
        return (UserShareInfoDO) o;
    }

    public UserShareInfoVO getShareInfo(Long learnId, Long currentUserId) {
        UserShareInfoDO userShareInfoDO = getShareInfoByLearnId(learnId);
        if (null == userShareInfoDO) {
            return null;
        }
        UserShareInfoVO userShareInfoVO = UserShareInfoVO.from(userShareInfoDO);
        UsersVO usersVO = usersService.find(userShareInfoVO.getUserId());
        userShareInfoVO.setAvatarUrl(usersVO.getAvatarUrl());
        userShareInfoVO.setUserShareZanVOList(getZanList(learnId));
        userShareInfoVO.setUserShareCardVOList(getCardList(learnId));
        userShareInfoVO.setIfCard(usersShareCardRepository.findByLearnIdAndCardUserId(learnId, currentUserId) == null ? false:true);
        userShareInfoVO.setIfZan(usersShareZanRepository.findByLearnIdAndZanUserId(learnId, currentUserId) ==null ? false:true);
        return userShareInfoVO;
    }

    public List<UserShareCardVO> getCardList(Long learnId) {
        String shareCardKey = RedisKeyConst.getShareCardList(learnId);
        Object o = redisTemplate.opsForValue().get(shareCardKey);
        if (o != null) {
            return (List<UserShareCardVO>) o;
        }
        List<UserShareCardDO> allByLearnId = null;
        if (o == null) {
            allByLearnId = usersShareCardRepository.findAllByLearnIdOrderByCreateTimeDesc(learnId);
        }
        if (null == allByLearnId || allByLearnId.size() == 0) {
            return new ArrayList<>();
        }
        List<UserShareCardVO> shareCardVOList = Lists.newArrayList();
        for(UserShareCardDO d :allByLearnId){
            UserShareCardVO userShareCardVO = UserShareCardVO.from(d);
            shareCardVOList.add(userShareCardVO);
            UsersVO usersVO = usersService.find(userShareCardVO.getCardUserId());
            userShareCardVO.setCardUserAvatar(usersVO.getAvatarUrl());
            userShareCardVO.setCardUserName(usersVO.getName());
        };
        redisTemplate.opsForValue().set(shareCardKey, shareCardVOList, 1, TimeUnit.DAYS);
        return shareCardVOList;
    }

    public List<UserShareZanVO> getZanList(Long learnId) {
        String shareZanKey = RedisKeyConst.getShareZanList(learnId);
        Object o = redisTemplate.opsForValue().get(shareZanKey);
        if (o != null) {
            return (List<UserShareZanVO>) o;
        }
        List<UserShareZanDO> allByLearnId = null;
        if (o == null) {
            allByLearnId = usersShareZanRepository.findAllByLearnIdOrderByCreateTimeDesc(learnId);
        }
        if (null == allByLearnId || allByLearnId.size() == 0) {
            return new ArrayList<>();
        }
        List<UserShareZanVO> shareZanVOList = Lists.newArrayList();
        for(UserShareZanDO d : allByLearnId){
            UserShareZanVO userShareZanVO = UserShareZanVO.from(d);
            shareZanVOList.add(userShareZanVO);
            UsersVO usersVO = usersService.find(userShareZanVO.getZanUserId());
            userShareZanVO.setZanUserAvatar(usersVO.getAvatarUrl());
            userShareZanVO.setZanUserName(usersVO.getName());
        };
        redisTemplate.opsForValue().set(shareZanKey, shareZanVOList, 1, TimeUnit.DAYS);
        return shareZanVOList;
    }
    public List<JSONObject> getZanAvatarList(Long learnId) {
        List<UserShareZanVO> zanList = getZanList(learnId);
        if (AssertUtil.isEmpty(zanList)) {
            return new ArrayList<>(0);
        }
        return zanList.stream().map(z ->{
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("zanUserName",z.getZanUserName());
            jsonObject.put("zanUserAvatar",z.getZanUserAvatar());
            return jsonObject;
        }).collect(Collectors.toList());
    }
    public List<JSONObject> getCardAvatarList(Long learnId) {
        List<UserShareCardVO> cardList = getCardList(learnId);
        if (AssertUtil.isEmpty(cardList)) {
            return new ArrayList<>(0);
        }
        return cardList.stream().map(z ->{
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("cardUserName",z.getCardUserName());
            jsonObject.put("cardUserAvatar",z.getCardUserAvatar());
            return jsonObject;
        }).collect(Collectors.toList());
    }

    public UserShareZanVO addZan(UserShareZanDO userShareZanDO) {
        UserShareZanDO byLearnIdAndZanUserId = usersShareZanRepository.findByLearnIdAndZanUserId(userShareZanDO.getLearnId(), userShareZanDO.getZanUserId());
        if (null != byLearnIdAndZanUserId) {
            throw new CheckRunException("请勿重复点赞");
        }
        byLearnIdAndZanUserId = usersShareZanRepository.save(userShareZanDO);
        redisTemplate.delete(RedisKeyConst.getShareZanList(userShareZanDO.getLearnId()));
        return UserShareZanVO.from(byLearnIdAndZanUserId);
    }
    public UserShareCardVO addCard(UserShareCardDO userShareCardDO) {
        UserShareCardDO byLearnIdAndCardUserId = usersShareCardRepository.findByLearnIdAndCardUserId(userShareCardDO.getLearnId(), userShareCardDO.getCardUserId());
        if (null != byLearnIdAndCardUserId) {
            throw new CheckRunException("请勿重复打卡");
        }
        byLearnIdAndCardUserId = usersShareCardRepository.save(userShareCardDO);
        redisTemplate.delete(RedisKeyConst.getShareCardList(userShareCardDO.getLearnId()));
        return UserShareCardVO.from(byLearnIdAndCardUserId);
    }

    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    @Lazy
    private UsersServiceImpl usersService;
    @Autowired
    @Lazy
    private UsersStudyServiceImpl usersStudyService;

    private final UsersShareInfoRepository usersShareInfoRepository;
    private final UsersShareCardRepository usersShareCardRepository;
    private final UsersShareZanRepository usersShareZanRepository;
    public UsersShareServiceImpl(UsersShareInfoRepository usersShareInfoRepository,
                                 UsersShareCardRepository usersShareCardRepository,
                                 UsersShareZanRepository usersShareZanRepository) {
        this.usersShareCardRepository = usersShareCardRepository;
        this.usersShareZanRepository = usersShareZanRepository;
        this.usersShareInfoRepository = usersShareInfoRepository;
    }

}
